package com.tongtong.controller.email.utils;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.tongtong.common.WebConstants;
import com.tongtong.controller.email.entity.TtEmailConfig;
import com.tt.utils.EncryptionUtils;
import lombok.SneakyThrows;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.net.URL;
import java.util.*;

public class SendEmailUtils {

    // 是否要求身份认证
    private final String IS_AUTH = "true";

    // 是否启用调试模式（启用调试模式可打印客户端与服务器交互过程时一问一答的响应消息）
    private final String IS_ENABLED_DEBUG_MOD = "false";

    //验证账号密码是否正确
    public boolean validateEmailPassword(TtEmailConfig emailConfig) {
        Properties properties = new Properties();
        properties.put("mail.smtp.host", emailConfig.getHost());
        properties.put("mail.smtp.port", emailConfig.getPort());
        properties.put("mail.transport.protocol", emailConfig.getProtocol());
        properties.put("mail.smtp.auth", "true");
        properties.put("mail.smtp.starttls.enable", "true");
        properties.put("mail.smtp.ssl.protocols", "TLSv1.2");
        properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");

        Session session = Session.getInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(emailConfig.getEmail(), emailConfig.getPassword());
            }
        });

        try {
            // Attempt to connect to the mail server
            session.getTransport().connect();
            return true; // Connection successful, credentials are valid
        } catch (Exception e) {
            e.printStackTrace();
            return false; // Connection failed, credentials are invalid
        }
    }

    public boolean sendMultipleEmail(SendEmail sendEmail, TtEmailConfig emailConfig) {
        if (sendEmail.getTo() == null || sendEmail.getTo().isEmpty()) {
            throw new IllegalArgumentException("Recipient list cannot be empty");
        }
        Transport transport = null;
        try {
            Session session = initProps(emailConfig);
            MimeMessage message = createMimeMessage(sendEmail, session);
            // 创建邮件内容
            Multipart mailContent = createMailContent(sendEmail);
            // 将邮件内容设置到消息中
            message.setContent(mailContent);
            transport = session.getTransport();
            transport.connect(emailConfig.getEmail(), EncryptionUtils.decryptWithAES(emailConfig.getPassword(), WebConstants.PASSWORDKEY));
            transport.sendMessage(message, message.getAllRecipients());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (transport != null) {
                try {
                    transport.close();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    private Session initProps(TtEmailConfig emailConfig) {
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", emailConfig.getProtocol());
        props.setProperty("mail.smtp.host", emailConfig.getHost());
        props.setProperty("mail.smtp.port", emailConfig.getPort().toString());
        props.setProperty("mail.smtp.auth", IS_AUTH);
        props.setProperty("mail.debug", IS_ENABLED_DEBUG_MOD);
        props.setProperty("mail.smtp.starttls.enable", "true");
        props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");
        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            @SneakyThrows
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(emailConfig.getEmail(), EncryptionUtils.decryptWithAES(emailConfig.getPassword(), WebConstants.PASSWORDKEY));
            }
        });
        return session;
    }

    private MimeMessage createMimeMessage(SendEmail sendEmail, Session session) throws MessagingException {
        // 创建MimeMessage实例对象
        MimeMessage message = new MimeMessage(session);
        // 设置发件人
        message.setFrom(new InternetAddress(sendEmail.getFrom()));
        // 设置邮件主题
        message.setSubject(sendEmail.getTitle());
        // 设置收件人
        Address[] toS = listToInternetAddressArray(sendEmail.getTo());
        message.setRecipients(Message.RecipientType.TO, toS);
        // 抄送
        if (CollectionUtils.isNotEmpty(sendEmail.getCc())) {
            Address[] ccS = listToInternetAddressArray(sendEmail.getCc());
            message.setRecipients(Message.RecipientType.CC, ccS);
        }
        // 密送 (不会在邮件收件人名单中显示出来)
        if (CollectionUtils.isNotEmpty(sendEmail.getBcc())) {
            Address[] bccS = listToInternetAddressArray(sendEmail.getBcc());
            message.setRecipients(Message.RecipientType.BCC, bccS);
        }
        // 设置发送时间
        message.setSentDate(new Date());

        return message;
    }

    /**
     * 将List<String>转换为InternetAddress数组
     *
     * @param emailList 包含电子邮件地址的列表
     * @return InternetAddress数组
     * @throws AddressException 如果电子邮件地址格式不正确
     */
    public Address[] listToInternetAddressArray(List<String> emailList) {
        return emailList.stream()
                .map(email -> {
                    try {
                        return new InternetAddress(email);
                    } catch (AddressException e) {
                        // 可以选择记录日志或者抛出异常
                        throw new RuntimeException("Invalid email address: " + email, e);
                    }
                })
                .toArray(InternetAddress[]::new);
    }


    private Multipart createMailContent(SendEmail sendEmail) throws Exception {
        // 创建一个MIME子类型为"mixed"的MimeMultipart对象，表示这是一封混合组合类型的邮件
        MimeMultipart mailContent = new MimeMultipart("mixed");
        // 添加附件
        if (Objects.nonNull(sendEmail.getFiles())) {
            for (Map.Entry<String, String> file : sendEmail.getFiles().entrySet()) {
                addAttachment(mailContent, file.getValue(), file.getKey());
            }
        }
        // 添加邮件正文
        MimeBodyPart bodyPart = new MimeBodyPart();
        MimeMultipart body = createBodyPart(sendEmail);
        bodyPart.setContent(body);
        mailContent.addBodyPart(bodyPart);
        return mailContent;
    }

    private void addAttachment(Multipart multipart, String filePath, String fileName) throws Exception {
        MimeBodyPart attachment = new MimeBodyPart();
        DataSource dataSource = null;
        if (filePath.startsWith("https://") || filePath.startsWith("http://")) {
            dataSource = new URLDataSource(new URL(filePath));
        } else {
            dataSource = new FileDataSource(filePath);
        }

        attachment.setDataHandler(new DataHandler(dataSource));
        attachment.setFileName(MimeUtility.encodeText(fileName));
        multipart.addBodyPart(attachment);
    }

    private MimeMultipart createBodyPart(SendEmail sendEmail) throws MessagingException {
        // 邮件正文由html和图片构成
        MimeMultipart body = new MimeMultipart("related");

        // 添加正文图片
        if(Objects.nonNull(sendEmail.getImags())){
            StringBuffer stringBuffer = new StringBuffer();
            for(Map.Entry<String,String> img : sendEmail.getImags().entrySet()){
                addImagePart(body, img.getValue(), img.getKey());
                stringBuffer.append("<img src='cid:"+img.getKey()+"' />");
            }
            sendEmail.setContent(sendEmail.getContent()+stringBuffer);
        }
        // 添加HTML内容
        MimeBodyPart htmlPart = new MimeBodyPart();
        MimeMultipart htmlContent = new MimeMultipart("alternative");
        MimeBodyPart htmlBodyPart = new MimeBodyPart();
        htmlBodyPart.setContent(sendEmail.getContent(), "text/html;charset=utf-8");
        htmlContent.addBodyPart(htmlBodyPart);
        htmlPart.setContent(htmlContent);
        body.addBodyPart(htmlPart);

        return body;
    }

    private void addImagePart(Multipart multipart, String filePath, String contentId) throws MessagingException {
        MimeBodyPart imagePart = new MimeBodyPart();
        DataSource dataSource = new FileDataSource(filePath);
        imagePart.setDataHandler(new DataHandler(dataSource));
        imagePart.setContentID("<" + contentId + ">");
        imagePart.setDisposition(MimeBodyPart.INLINE);
        multipart.addBodyPart(imagePart);
    }


    public static class SendEmail {
        private String from;
        private List<String> to;
        private List<String> cc;
        private List<String> bcc;
        private String title;
        private String content;
        private Session session;
        private Map<String, String> imags;
        private Map<String, String> files;

        public String getFrom() {
            return from;
        }

        public void setFrom(String from) {
            this.from = from;
        }

        public List<String> getTo() {
            return to;
        }

        public void setTo(List<String> to) {
            this.to = to;
        }

        public List<String> getCc() {
            return cc;
        }

        public void setCc(List<String> cc) {
            this.cc = cc;
        }

        public List<String> getBcc() {
            return bcc;
        }

        public void setBcc(List<String> bcc) {
            this.bcc = bcc;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }

        public Session getSession() {
            return session;
        }

        public void setSession(Session session) {
            this.session = session;
        }

        public Map<String, String> getImags() {
            return imags;
        }

        public void setImags(Map<String, String> imags) {
            this.imags = imags;
        }

        public Map<String, String> getFiles() {
            return files;
        }

        public void setFiles(Map<String, String> files) {
            this.files = files;
        }
    }


}

